/*
 * @Author: your name
 * @Date: 2025-07-25 14:58:47
 * @LastEditTime: 2025-08-05 15:52:52
 * @LastEditors: LAPTOP-HAM9H5E2
 * @Description: In User Settings Edit
 * @FilePath: \driver-backend\src\auth\auth.guard.ts
 */
// Jwt 守卫
import { JwtService } from '@nestjs/jwt';
// CanActivate：守卫必须实现的接口，定义了一个canActivate方法
// ExecutionContext：提供当前请求的 上下文信息（如HTTP 请求、websocket 消息等）
import { Injectable, CanActivate, ExecutionContext, UnauthorizedException } from '@nestjs/common';
// 是 NestJS 提供的一个工具类，用于读取附加到类、方法或属性上的元数据
import { Reflector } from '@nestjs/core';
import { JWT_SECTET_KEY } from './auth.jwt.secrect';
import { IS_PUBLIC_KEY } from './public.decorator';

@Injectable()
// 定义守卫类
export class AuthGuard implements CanActivate {
    constructor(private jwtService: JwtService, private reflector: Reflector) { }
    async canActivate(context: ExecutionContext): Promise<boolean> {
        // 拿到当前api，请求头信息
        const isPublic = this.reflector.getAllAndOverride(IS_PUBLIC_KEY, [
            // 当前路由处理程序
            context.getHandler(),
            // 当前控制器类
            context.getClass()
        ])
        if (isPublic) {
            return true
        }

        const request = context.switchToHttp().getRequest()
        const token = extractTokenFromHeader(request)

        if (!token) {
            throw new UnauthorizedException()
        }

        try {
            // 解析出用户信息，然后塞到请求头里，以后需要用户信息直接请求头拿
            const payload = await this.jwtService.verifyAsync(token, {
                secret: JWT_SECTET_KEY
            })
            // 请求头包含用户信息
            request['user'] = payload
        } catch (e) {
            throw new UnauthorizedException({
                code: 10010,
                message: '用户身份已过期',
                error: null
            })
        }

        return true
    }
}

function extractTokenFromHeader(request) {
    const [type, token] = request.headers.authorization?.split(' ') ?? []
    return type === 'Bearer' ? token : '';
}
